package com.mida.bms.report.service.impl;

import com.alibaba.fastjson.JSONObject;

import com.mida.bms.report.entity.*;
import com.mida.bms.report.mapper.*;
import com.mida.bms.report.service.DocStructParagraphService;
import com.mida.bms.report.service.SoidService;
import com.mida.bms.report.vo.*;
import com.mida.tool.common.result.ActionResult;
import com.mida.tool.common.result.BaseResult;
import com.mida.tool.common.result.ListResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ：wang xiao le
 * @description：TODO 结构化模板段落实现层
 * @date ：2021/4/6 11:54
 */
@Service
@Transactional
@Slf4j
public class DocStructParagraphServiceImpl extends BaseResult implements DocStructParagraphService {


    public static final Long DIAGNOSE = 3529L;  //医学影像学诊断段落
    public static final Long SEE = 3524L; //影像学所见段落
    //    @Autowired
//    private CMOIDGanerator cmoidGanerator;
//
//    @Autowired
//    private CMDtOidMapper cmDtOidMapper;
    @Autowired
    private SoidService soidService;

    @Autowired
    private DocStructParagraphMapper docStructParagraphMapper;

    @Autowired
    private DocStructFragmentMapper docStructFragmentMapper;

    @Autowired
    private DocStructTemplateSlotMapper docStructTemplateSlotMapper;

    @Autowired
    private DocStructSlotValueMapper docStructSlotValueMapper;

    @Autowired
    private DocStructCssMapper docStructCssMapper;

    @Autowired
    private DocCustomerContentMapper docCustomerContentMapper;

//    @Autowired
//    CommonNoumenonService commonNoumenonService;
//
//    @Autowired
//    CommonKnwConceptualDetailService commonKnwConceptualDetailService;

    @Autowired
    private DocCustomTextJsonMapper docCustomTextJsonMapper;

    @Autowired
    private DocCustomTextImgMapper docCustomTextImgMapper;
    @Autowired
    private DocStructTemplateClobContentMapper docStructTemplateClobContentMapper;

    @Value("${nginx.url}")
    private String nginxUrl;

    @Value("${ftp.imgPath}")
    private String imgPath;

    @Value("${ftp.server.host}")
    private String ftpHost;

    @Value("${ftp.server.port}")
    private int ftpPort;

    @Value("${ftp.server.username}")
    private String ftpUserName;

    @Value("${ftp.server.password}")
    private String ftpPassword;

    Map<String, String> mapCss;

    @Override
    public ActionResult add(DocStructRequestVo docStructRequestVo) {
        log.info("开始保存报告模板");
        StopWatch stopWatch = StopWatch.createStarted();
        ActionResult result = new ActionResult();
        List<DocStructVo> docStructVoList = docStructRequestVo.getDocReportVoList();
        //校验参数合法性
        if (CollectionUtils.isEmpty(docStructVoList)) {
            result.setStatus(HttpStatus.BAD_REQUEST.value());
            result.setMessage("模板报告数据不能为空");
            return result;
        }

        try {
            //1. 删除原有模板结构
            Long stTemplateInfoSoid = docStructVoList.get(0).getStTemplateInfoSoid();
            if (!ObjectUtils.isEmpty(stTemplateInfoSoid)) {
                DocCustomTextJson docCustomTextJson = docCustomTextJsonMapper.selectBystTemplateInfoSoid(stTemplateInfoSoid);
                if (docCustomTextJson != null) {
                    docCustomTextJsonMapper.deleteBystTemplateInfoSoid(stTemplateInfoSoid);
                }
                docStructTemplateClobContentMapper.deleteBystTemplateInfoSoid(stTemplateInfoSoid);
            }
            //2.添加模板报告
            //存储到自定义文json存储信息中
            DocCustomTextJson docCustomTextJson = DocCustomTextJson.builder()
                    .customTextJsonSoid(soidService.getSoid())
                    .stTemplateInfoSoid(stTemplateInfoSoid)
                    .reportContent(JSONObject.toJSONString(docStructVoList))
                    .isDelete(0l)
                    .createDate(new Date())
                    .build();
            docCustomTextJsonMapper.insert(docCustomTextJson);
            //存储字符串
            List<DocStructTemplateClobContent> docStructTemplateClobContentList = docStructRequestVo.getDocStructTemplateClobContentList();
            if (CollectionUtils.isNotEmpty(docStructTemplateClobContentList)) {
                for (DocStructTemplateClobContent docStructTemplateClobContent : docStructTemplateClobContentList) {
                    docStructTemplateClobContent.setTemplateClobContentSoid(soidService.getSoid());
                    docStructTemplateClobContent.setIsDelete(0l);
                    docStructTemplateClobContent.setCreateDate(new Date());
                    docStructTemplateClobContent.setUpdateDate(new Date());
                    docStructTemplateClobContent.setStTemplateInfoSoid(stTemplateInfoSoid);
                    docStructTemplateClobContentMapper.insertSelective(docStructTemplateClobContent);
                }
            }


            buildActionSuccess(result);
        } catch (Exception e) {
            log.error("保存报告模板发送异常", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            buildActionWarn(result, "保存报告模板失败");
        } finally {

            stopWatch.stop();
            log.info("本次保存报告模板耗时: " + stopWatch.getTime() + "ms");
        }
        return result;
    }

    /**
     * 获取报告模板缩略图
     *
     * @param stTemplateInfoSoid
     * @return
     */
    @Override
    public ListResult<String> getTemplateImg(Long stTemplateInfoSoid) {
        log.info("开始获取报告模板缩略图,查询条件: " + stTemplateInfoSoid);
        StopWatch stopWatch = StopWatch.createStarted();
        ListResult listResult = new ListResult();
        if (ObjectUtils.isEmpty(stTemplateInfoSoid)) {
            log.error("报告模板基本信息soid不能为空");
            buildBadRequestListWarn(listResult, "报告模板基本信息soid不能为空");
            return listResult;
        }

        try {
            DocCustomTextImg docCustomTextImg = docCustomTextImgMapper.selectByStTemplateSoid(stTemplateInfoSoid);
            String path = null;
            if (docCustomTextImg != null) {
                String image = docCustomTextImg.getImagePath();
                if (image != null) {
                    StringBuffer stringBuffer = new StringBuffer(nginxUrl);
                    StringBuffer url = stringBuffer.append("/").append(imgPath).append("/").append(image);
                    path = url.toString();
                }
            }
            buildListSuccess(listResult, path);
        } catch (Exception e) {
            log.error("获取报告模板缩略图发送异常", e);
            buildListWarn(listResult, "获取报告模板缩略图失败");
        } finally {
            stopWatch.stop();
            log.info("本次查询报告模板缩略图耗时: " + stopWatch.getTime() + "ms");
        }
        return listResult;
    }

    /**
     * 保存模板
     *
     * @param docStructParagraphVoListChange 模板段落
     */
    private void saveTemplate(List<DocStructParagraphVo> docStructParagraphVoListChange) {
        for (DocStructParagraphVo docStructParagraphVo : docStructParagraphVoListChange) {
            //1.1.1保存段落基本信息
            DocStructParagraph docStructParagraph = new DocStructParagraph();
            BeanUtils.copyProperties(docStructParagraphVo, docStructParagraph);//vo--->entity
            docStructParagraph.setCreateDate(new Date());
            docStructParagraph.setUpdateDate(new Date());
            docStructParagraph.setIsDelete(0L);
//            Long seq = cmoidGanerator.getSOID();
            Long seq = soidService.getSoid();
            docStructParagraph.setStParagraphSoid(seq);
            docStructParagraphVo.setStParagraphSoid(seq);//在Vo中设置段落soid,为了后续使用
            docStructParagraphMapper.insert(docStructParagraph);

//                String oid = cmoidGanerator.getOID(1);
//                DtOid dtOid = new DtOid();
//                dtOid.setOid(oid);
//                dtOid.setSoid(stParagraphSoid);
//                cmDtOidMapper.insert(dtOid);

            //1.1.2保存段落slot和slotValue
            List<DocStructTemplateSlotVo> docParagraphSlotVoList = docStructParagraphVo.getDocParagraphSlotVoList();
            if (CollectionUtils.isNotEmpty(docParagraphSlotVoList)) {
                Long stParagraphSoid = docStructParagraphVo.getStParagraphSoid();//段落Soid
                for (DocStructTemplateSlotVo docStructTemplateSlotVo : docParagraphSlotVoList) {
                    saveTemplateSlot(stParagraphSoid, docStructTemplateSlotVo);//保存结构化模板报告段落Slot
                }
            }

            //3.添加报告片段
            List<DocStructFragmentVo> docStructFragmentVoList = docStructParagraphVo.getDocStructFragmentVoList();
            if (CollectionUtils.isNotEmpty(docStructFragmentVoList)) {
                //循环处理片段
                for (DocStructFragmentVo docStructFragmentVo : docStructFragmentVoList) {

                    //2.1.1保存结构化模板报告片段基本信息
                    docStructFragmentVo.setStParagraphSoid(docStructParagraphVo.getStParagraphSoid());
                    if (docStructFragmentVo.getNoumenonSoid() != null) {//去除片段自定义文本
                        addDocStructFragment(docStructFragmentVo);
                    }
                    //2.1.2保存片段slot和slotValue
                    List<DocStructTemplateSlotVo> docStructTemplateSlotVoList = docStructFragmentVo.getDocStructTemplateSlotVoList();
                    if (CollectionUtils.isNotEmpty(docStructTemplateSlotVoList)) {
                        Long stFragmentSoid = docStructFragmentVo.getStFragmentSoid();

                        for (DocStructTemplateSlotVo docStructTemplateSlotVo : docStructTemplateSlotVoList) {
                            if (docStructTemplateSlotVo.getSlotSoid() != null) {//去除slot自定义文本
                                //保存结构化模板报告片段Slot
                                saveTemplateSlot(stFragmentSoid, docStructTemplateSlotVo);
                            }
                        }
                    }

                }
            }
        }
    }

    @Override
    public ListResult<DocStructRequestVo> getTemplate(Long stTemplateInfoSoid) {
        ListResult<DocStructRequestVo> lr = new ListResult<>();
        DocStructRequestVo docStructRequestVo = new DocStructRequestVo();
        String stMongodbSoid = null;
        if (ObjectUtils.isEmpty(stTemplateInfoSoid)) {
            log.error("报告模板基本信息soid不能为空");
            buildBadRequestListWarn(lr, "报告模板基本信息soid不能为空");
            return lr;
        }
        DocCustomTextJson docCustomTextJson = docCustomTextJsonMapper.selectBystTemplateInfoSoid(stTemplateInfoSoid);
        List<DocStructVo> docReportVoList = null;
        if (docCustomTextJson != null) {
            String reportContent = docCustomTextJson.getReportContent();
            docReportVoList = JSONObject.parseArray(reportContent, DocStructVo.class);
        }
        List<DocStructTemplateClobContent> docStructTemplateClobContentList = docStructTemplateClobContentMapper.selectBystTemplateInfoSoid(stTemplateInfoSoid);
        docStructRequestVo.setDocReportVoList(docReportVoList);
        docStructRequestVo.setDocStructTemplateClobContentList(docStructTemplateClobContentList);
        buildListSuccess(lr, docStructRequestVo);
        return lr;
    }

    /**
     * 更新段落或报告slot和slotValue
     *
     * @param docFragraSlotVoList 段落或片段slot集合
     * @param stFragraSoid        段落或片段soid
     */
    private void updatePraOrFraTemplate(List<DocStructTemplateSlotVo> docFragraSlotVoList, Long stFragraSoid) {
        for (DocStructTemplateSlotVo docStructTemplateSlotVo : docFragraSlotVoList) {
            Long isDelete = docStructTemplateSlotVo.getIsDelete();
            if (ObjectUtils.isEmpty(docStructTemplateSlotVo.getStTemplateSlotSoid()) && (ObjectUtils.isEmpty(isDelete) || isDelete == 0L)) {//首次添加
                //1.3.1保存段落或片段slot
                saveTemplateSlot(stFragraSoid, docStructTemplateSlotVo);

                // 片段Slot的CSs值map追加
                if (docStructTemplateSlotVo.getDocStructCssVo() != null
                        && org.apache.commons.lang.StringUtils.isNotEmpty(
                        docStructTemplateSlotVo.getDocStructCssVo().getStructCssValue())) {
                    mapCss.put(String.valueOf(docStructTemplateSlotVo.getStTemplateSlotSoid()),
                            docStructTemplateSlotVo.getDocStructCssVo().getStructCssValue());
                } else {
                    mapCss.put(String.valueOf(docStructTemplateSlotVo.getStTemplateSlotSoid()), "");
                }


            } else if (!ObjectUtils.isEmpty(docStructTemplateSlotVo.getStTemplateSlotSoid()) && docStructTemplateSlotVo.getIsDelete() != null && docStructTemplateSlotVo.getIsDelete() == 1) {//1.3.2删除段落slot
                Long stTemplateSlotSoid = docStructTemplateSlotVo.getStTemplateSlotSoid();
                if (!ObjectUtils.isEmpty(stTemplateSlotSoid)) {
                    //删除slotValue
                    docStructSlotValueMapper.deleteByStTemplateSlotSoid(stTemplateSlotSoid);
                    //删除slot
                    docStructTemplateSlotMapper.deleteByPrimaryKey(stTemplateSlotSoid);
                }
            } else if (!ObjectUtils.isEmpty(docStructTemplateSlotVo.getStTemplateSlotSoid())) {//1.3.3编辑
                //更新slot位置
                DocStructTemplateSlot docStructTemplateSlot = new DocStructTemplateSlot();
                docStructTemplateSlot.setStTemplateSlotSoid(docStructTemplateSlotVo.getStTemplateSlotSoid());
                docStructTemplateSlot.setSerialNo(docStructTemplateSlotVo.getSerialNo());
                docStructTemplateSlot.setUpdateDate(new Date());
                if (docStructTemplateSlotVo.getConceptualDetailSoid() != null) {
                    docStructTemplateSlot.setConceptualDetailSoid(docStructTemplateSlotVo.getConceptualDetailSoid());
                }
                docStructTemplateSlotMapper.updateByPrimaryKeySelective(docStructTemplateSlot);
                //目标slotValue
                DocStructSlotValueVo valueTarget = docStructTemplateSlotVo.getDocStructSlotValueVo();
                Long stTemplateSlotSoid = docStructTemplateSlotVo.getStTemplateSlotSoid();
                if (!ObjectUtils.isEmpty(stTemplateSlotSoid)) {
                    //获取源slotValue
                    DocStructSlotValueVo valueSource = docStructSlotValueMapper.selectByStTemplateSlotSoid(stTemplateSlotSoid);
                    if (valueTarget != null && !StringUtils.isEmpty(valueTarget.getDataValue()) && valueSource == null) {//添加slotValue
                        saveSlotVaule(valueTarget, stTemplateSlotSoid);
                    } else if (valueTarget != null && valueSource != null) {//修改
                        if (!valueTarget.equals(valueSource)) {//判断dataValue是否修改
                            DocStructSlotValue docStructSlotValue = new DocStructSlotValue();
                            BeanUtils.copyProperties(valueSource, docStructSlotValue);
                            docStructSlotValue.setDataValue(valueTarget.getDataValue());
                            docStructSlotValue.setUpdateDate(new Date());
                            docStructSlotValue.setIsDelete(0L);
                            docStructSlotValueMapper.updateByPrimaryKey(docStructSlotValue);
                        }
                    }

                    // 片段Slot的CSs值map追加
                    if (docStructTemplateSlotVo.getDocStructCssVo() != null
                            && org.apache.commons.lang.StringUtils.isNotEmpty(
                            docStructTemplateSlotVo.getDocStructCssVo().getStructCssValue())) {
                        mapCss.put(String.valueOf(docStructTemplateSlotVo.getStTemplateSlotSoid()),
                                docStructTemplateSlotVo.getDocStructCssVo().getStructCssValue());
                    } else {
                        mapCss.put(String.valueOf(docStructTemplateSlotVo.getStTemplateSlotSoid()), "");
                    }
                }
            }
        }
    }

    /**
     * 保存结构化模板报告段落片段Slot
     *
     * @param stFragraSoid            结构化模板报告段落片段soid
     * @param docStructTemplateSlotVo 结构化模板报告段落片段SlotVo
     */
    private void saveTemplateSlot(Long stFragraSoid, DocStructTemplateSlotVo docStructTemplateSlotVo) {
        //1.2.1保存段落slot
        DocStructTemplateSlot docStructTemplateSlot = new DocStructTemplateSlot();
        BeanUtils.copyProperties(docStructTemplateSlotVo, docStructTemplateSlot);//vo--->entity
        docStructTemplateSlot.setCreateDate(new Date());
        docStructTemplateSlot.setUpdateDate(new Date());
        docStructTemplateSlot.setIsDelete(0L);
        docStructTemplateSlot.setStFragraSoid(stFragraSoid);
        docStructTemplateSlotVo.setStFragraSoid(stFragraSoid);

//        Long seq2 = cmoidGanerator.getSOID();
        Long seq2 = soidService.getSoid();
        docStructTemplateSlot.setStTemplateSlotSoid(seq2);
        docStructTemplateSlotVo.setStTemplateSlotSoid(seq2);//为方便下面使用
        docStructTemplateSlotMapper.insert(docStructTemplateSlot);
//                            String oid2 = cmoidGanerator.getOID(1);
//                            DtOid dtOid2 = new DtOid();
//                            dtOid.setOid(oid2);
//                            dtOid.setSoid(seq2);
//                            cmDtOidMapper.insert(dtOid2);

        //1.2.2保存段落slotValue
        Long stTemplateSlotSoid = docStructTemplateSlot.getStTemplateSlotSoid();
        DocStructSlotValueVo docStructSlotValueVo = docStructTemplateSlotVo.getDocStructSlotValueVo();
        if (docStructSlotValueVo != null) {
            saveSlotVaule(docStructSlotValueVo, stTemplateSlotSoid);
        }
    }

    /**
     * 保存结构化模板报告段落片段SlotValue
     *
     * @param docStructSlotValueVo 模板报告段落片段SlotValueVo实体类
     * @param stTemplateSlotSoid   结构化模板报告段落片段soid
     */
    private void saveSlotVaule(DocStructSlotValueVo docStructSlotValueVo, Long stTemplateSlotSoid) {
        DocStructSlotValue docStructSlotValue = new DocStructSlotValue();
        BeanUtils.copyProperties(docStructSlotValueVo, docStructSlotValue);
        docStructSlotValue.setStTempleSlotSoid(stTemplateSlotSoid);
        docStructSlotValueVo.setStTempleSlotSoid(stTemplateSlotSoid);
        docStructSlotValue.setCreateDate(new Date());
        docStructSlotValue.setUpdateDate(new Date());
        docStructSlotValue.setIsDelete(0L);
//        Long valueSoid = cmoidGanerator.getSOID();
        Long valueSoid = soidService.getSoid();
        docStructSlotValue.setStSlotValueSoid(valueSoid);
        docStructSlotValueVo.setStSlotValueSoid(valueSoid);
        docStructSlotValueMapper.insert(docStructSlotValue);

//        String valueOid = cmoidGanerator.getOID(1);
//        DtOid valueDtOid = new DtOid();
//        valueDtOid.setOid(valueOid);
//        valueDtOid.setSoid(valueSoid);
//        cmDtOidMapper.insert(valueDtOid);
    }

    /**
     * 根据stFragraSoid删除 报告模板slot和关联的slotValue
     *
     * @param stFragraSoid 结构化报告模板段落片段标识
     */
    private void deleteDocSlotAndDocSlotValue(Long stFragraSoid) {
        //获取模板slot集合
        List<DocStructTemplateSlotVo> slotVos = docStructTemplateSlotMapper.selectByFragraSoid(stFragraSoid);
        //获取模板slotSoid，并根据templateSlotSoid遍历删除报告slotValue
        if (CollectionUtils.isNotEmpty(slotVos)) {
            slotVos.stream()
                    .map(DocStructTemplateSlot::getStTemplateSlotSoid)
                    .collect(Collectors.toList())
                    .forEach(templateSlotSoid -> docStructSlotValueMapper.deleteByStTemplateSlotSoid(templateSlotSoid));//删除报告slotValue
        }
        docStructTemplateSlotMapper.deleteByFragraSoid(stFragraSoid);//删除模板slot
    }

    /**
     * 保存结构化模板报告片段
     *
     * @param docStructFragmentVo
     */
    private void addDocStructFragment(DocStructFragmentVo docStructFragmentVo) {
        DocStructFragment docStructFragment = new DocStructFragment();
        BeanUtils.copyProperties(docStructFragmentVo, docStructFragment);//vo--->entity
        docStructFragment.setCreateDate(new Date());
        docStructFragment.setUpdateDate(new Date());
        docStructFragment.setIsDelete(0L);
        docStructFragment.setStParagraphSoid(docStructFragmentVo.getStParagraphSoid());
//        Long seq = cmoidGanerator.getSOID();
        Long seq = soidService.getSoid();
        docStructFragment.setStFragmentSoid(seq);
        docStructFragmentVo.setStFragmentSoid(seq);//为了后续使用
        docStructFragmentMapper.insert(docStructFragment);//添加模板片段信息
//        String oid = cmoidGanerator.getOID(1);
//        DtOid dtOid = new DtOid();
//        dtOid.setOid(oid);
//        dtOid.setSoid(seq);
//        cmDtOidMapper.insert(dtOid);

    }


    /**
     * @param stTemplateInfoSoid
     * @Description: 获取报告缩略图
     * @Date: Created in 14:53 2021/6/7
     */
    @Override
    public ListResult<DocStructRequestVo> getTemplatePic(Long stTemplateInfoSoid) {
        ListResult<DocStructRequestVo> lr = new ListResult<>();
        DocStructRequestVo docStructRequestVo = new DocStructRequestVo();
        if (ObjectUtils.isEmpty(stTemplateInfoSoid)) {
            log.error("模板基本信息soid不能为空");
            buildListWarn(lr, "模板基本信息soid不能为空");
            return lr;
        }
        DocCustomTextJson docCustomTextJson = docCustomTextJsonMapper.selectBystTemplateInfoSoid(stTemplateInfoSoid);
        if (docCustomTextJson == null) {
            log.error("模板为空");
            buildListWarn(lr, "模板为空");
            return lr;
        }
        List<DocStructVo> docReportVoList = null;
        if (docCustomTextJson != null) {
            String reportContent = docCustomTextJson.getReportContent();
            docReportVoList = JSONObject.parseArray(reportContent, DocStructVo.class);
        }
        //处理第一个模板数据，只保留特殊段落
        //过滤前三个段落，和最后一个
        List<DocStructParagraphVo> docStructParagraphVoList = docReportVoList.get(0).getDocStructParagraphVoList();
        //模板段落数有问题，直接返回空
        if (docStructParagraphVoList.size() < 4) {
            buildListSuccess(lr, null);
            return lr;
        }
        docStructParagraphVoList.remove(docStructParagraphVoList.size() - 1);

        for (int i = 0; i <= 2; i++) {
            docStructParagraphVoList.remove(0);
        }

        List<DocStructParagraphVo> docStructParagraphVoListResult = new ArrayList<>();

        for (DocStructVo docStructVo : docReportVoList) {
            if (ObjectUtils.isNotEmpty(docStructVo) && CollectionUtils.isNotEmpty(docStructVo.getDocStructParagraphVoList())) {
                docStructParagraphVoListResult.addAll(docStructVo.getDocStructParagraphVoList());
            }
        }

        DocStructVo docStructVo = new DocStructVo();
        docStructVo.setDocStructParagraphVoList(docStructParagraphVoListResult);
        docStructRequestVo.setDocStructVo(docStructVo);
        buildListSuccess(lr, docStructRequestVo);
        return lr;
    }
}
